package com.enterprise.application.orm.hibernate;

import com.enterprise.support.utility.Enterprise;
import com.enterprise.support.utility.Pagination;
import com.enterprise.support.utility.Validation;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: Zhanggaojiang
 * Date: 11-1-19
 * Time: 上午8:41
 * Email: z82422@gmail.com
 * 持久化 层 基础实现类   Hiberante 实现
 */

@Repository
@Transactional(propagation = Propagation.REQUIRED)
public class AbstractDaoImpl<T extends Enterprise> extends org.springframework.orm.hibernate3.support.HibernateDaoSupport implements IBaseDao<T> {
    private final static Logger logger = Logger.getLogger(AbstractDaoImpl.class);


    protected com.enterprise.application.orm.jdbc.AbstractDaoImpl jdbcLogic = new com.enterprise.application.orm.jdbc.AbstractDaoImpl();

    @Autowired
    public final void setHibernateTemplateExtend(HibernateTemplate hibernateTemplate) {
        setHibernateTemplate(hibernateTemplate);
    }


    /**
     * 增C
     *
     * @param entity
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public String save(T entity) {
        Object value = getHibernateTemplate().save(entity);
        return value != null ? value.toString() : null;
    }

    /**
     * 删D
     *
     * @param entity
     * @param
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void delete(T entity) {
        getHibernateTemplate().delete(entity);
    }

    /**
     * 改U
     *
     * @param entity
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void update(T entity) {
        getHibernateTemplate().saveOrUpdate(entity);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void merge(T entity) {
        getHibernateTemplate().merge(entity);
    }


    /**
     * Loading 数据
     *
     * @param entity
     * @param id
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public <T> T load(final Class<T> entity, final Serializable id) {
        return getHibernateTemplate().load(entity, id);
    }

    /**
     * get 数据
     *
     * @param entity
     * @param id
     * @return
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public <T> T get(final Class<T> entity, final Serializable id) {
        return getHibernateTemplate().get(entity, id);
    }

    //-------------------------------------------------------------------------
    // Convenience finder methods for HQL strings
    //-------------------------------------------------------------------------


    /**
     * 数据库操作 返回单条记录
     *
     * @param params
     * @return
     */

    public T find(T params) {
        List<T> values = finds(params);
        return (isEmpty(values)) ? null : values.get(0);
    }

    public T find(StringBuffer queryString, T params) {
        List<T> values = finds(queryString, params);
        return Validation.isEmpty(values) ? null : values.get(0);
    }


    public List<T> finds(T params) {
        return finds(generateSQL(params), params);
    }


    public List finds(final StringBuffer queryString, final T entity) {
        return getHibernateTemplate().executeFind(new HibernateCallback<Object>() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                long apptime = System.currentTimeMillis();
                Query query = session.createQuery(queryString.toString());
                query.setCacheable(true);
                if (entity != null) {
                    query.setProperties(entity);
                    if (!entity.isEmpty(Pagination.PAGE_SIZE)) {
                        query.setMaxResults(entity.getInt(Pagination.PAGE_SIZE));
                    }
                }
                List result = query.list();
                logger.debug("执行当前SQL耗时: " + (System.currentTimeMillis() - apptime) + "MS -> " + queryString + "\n");
                return result;
            }
        });

        /* Session session = getSession();
        try {
            long apptime = System.currentTimeMillis();
            Query query = session.createQuery(queryString.toString());
            query.setCacheable(true);
            if (entity != null) {
                query.setProperties(entity);
                if (!entity.isEmpty(Pagination.PAGE_SIZE)) {
                    query.setMaxResults(entity.getInt(Pagination.PAGE_SIZE));
                }
            }
            List result = query.list();
            logger.debug("执行当前SQL耗时: " + (System.currentTimeMillis() - apptime) + "MS -> " + queryString + "\n");
            return result;
        } finally {
            releaseSession(session);
        }*/
    }


    //-------------------------------------------------------------------------
    // Convenience finder methods for named queries
    //-------------------------------------------------------------------------

    public Integer count(final T enterprise) {
        return count(generateSQL(enterprise), enterprise);
    }

    public Integer count(StringBuffer queryResultString, final T enterprise) {

        Session session = getSession();
        try {
            /*生成 总记录数查询 SQL*/
            String tempQueryResultString = queryResultString.toString().toLowerCase();
            int i1 = tempQueryResultString.indexOf("from " + getPojoSimpleName(getPojoClass(enterprise)).toLowerCase());
            int i2 = tempQueryResultString.indexOf("where 1=1");
            int i3 = tempQueryResultString.indexOf("order by");
            String queryCountString = new String("select count(" + getPojoSimpleName(getPojoClass(enterprise)) + ") ");
            if (i2 == -1 && i3 == -1) {
                queryCountString += queryResultString.substring(i1, queryResultString.length());
            } else if (i2 != -1 && i3 != -1) {
                queryCountString += queryResultString.substring(i1, i2) + queryResultString.substring(i2, i3);
            } else if (i2 == -1 && i3 != -1) {
                queryCountString += queryResultString.substring(i1, i3);
            } else {
                queryCountString += queryResultString.substring(i1, queryResultString.length());
            }
            /*抓取*/
            for (Object value : enterprise.keySet()) {
                if (null != value && String.valueOf(value).indexOf("fetch") != -1) {
                    queryCountString = queryCountString.replace("LEFT JOIN FETCH " + getPojoSimpleName(getPojoClass(enterprise)) + "." + String.valueOf(value).substring(5) + " ", "");
                }
            }
            /**
             * 查询 总记录数 SQL
             */
            Query queryObject = session.createQuery(queryCountString);
            queryObject.setCacheable(true);
            queryObject.setProperties((Object) enterprise);
            return Integer.valueOf(queryObject.uniqueResult().toString());
        } finally {
            releaseSession(session);
        }
    }

    /**
     * -------------------------------------------------------------------------
     * 分页方法Pationation
     * -------------------------------------------------------------------------
     */
    public Pagination findPager(final T params) {
        return findPager(generateSQL(params), params);
    }

    public Pagination findPager(StringBuffer queryResultString, final T enterprise) {
        Session session = getSession();
        try {
            long apptime = System.currentTimeMillis();
            /*构造分页数据存储对象*/
            Pagination pagination = new Pagination(enterprise);
            enterprise.set(Pagination.PAGE_RESULT_COUNT, count(queryResultString, enterprise));
            /*查询分页结果数据 SQL*/
            Query query = session.createQuery(queryResultString.toString());
            query.setCacheable(true);
            query.setProperties((Object) enterprise);
            if (enterprise.getInt(Pagination.PAGE_RESULT_COUNT) != 0) {
                int i = (enterprise.getInt(Pagination.PAGE_INDEX) * enterprise.getInt(Pagination.PAGE_SIZE)) - enterprise.getInt(Pagination.PAGE_SIZE);
                query.setFirstResult(i < 0 ? 0 : i);
                query.setMaxResults(enterprise.getInt(Pagination.PAGE_SIZE));
                enterprise.set(Pagination.PAGE_RESULT, query.list());
            }
            logger.debug("执行当前SQL耗时(分页,双SQL): " + (System.currentTimeMillis() - apptime) + "MS -> " + queryResultString + "\n");
            return pagination;
        } finally {
            releaseSession(session);
        }
    }


    public boolean isEmpty(Object object) {
        return Validation.isEmpty(object);
    }

    public interface IBuilderSql {
        boolean execute(StringBuffer queryString, String simpleName);
    }

    public StringBuffer generateSQL(T params) {
        return builderSql(params, new IBuilderSql[]{});
    }

    public Class getPojoClass(T entity) {
        return entity.getClass().isAnonymousClass() ? entity.getClass().getSuperclass() : entity.getClass();
    }

    public String getPojoSimpleName(Class entity) {
        return entity.getSimpleName().toLowerCase();
    }

    public StringBuffer builderSql(T entity, IBuilderSql... builder) {
        Class pojoClass = getPojoClass(entity);
        String simpleName = getPojoSimpleName(pojoClass);
        StringBuffer queryString = new StringBuffer("from " + pojoClass.getSimpleName() + " " + simpleName + " where 1=1 ");
        if (!entity.isEmpty("id")) {
            queryString.append("and " + simpleName + ".id=:id ");
        } else if (!entity.isEmpty("greaterid")) {
            entity.set("id", entity.getInt("greaterid"));
            queryString.append("and " + simpleName + ".id > :id ");
        } else if (!entity.isEmpty("lessid")) {
            entity.set("id", entity.getInt("lessid"));
            queryString.append("and " + simpleName + ".id < :id ");
        }
        /*抓取*/
        for (Object value : entity.keySet()) {
            if (null != value && String.valueOf(value).indexOf("fetch") != -1) {
                queryString.insert(queryString.indexOf("where"), "LEFT JOIN FETCH " + simpleName + "." + String.valueOf(value).substring(5) + " ");
            }
        }
        /**
         * 当 builder 返回 Flash 时 排序自动拼装，否则手动拼装不启用下边逻辑
         */

        if (!isEmpty(builder) && builder.length > 0&&!builder[0].execute(queryString, simpleName)) {
            if (!entity.isEmpty(Pagination.PAGE_ORDER_BY) && entity.get(Pagination.PAGE_ORDER_BY) instanceof String) {
                append(queryString, "ORDER BY");
                append(queryString, entity.getString(Pagination.PAGE_ORDER_BY).replace("simpleName", simpleName));
                return queryString;
            }
        }
        append(queryString, "ORDER BY");
        append(queryString, simpleName + ".id desc");
        return queryString;
    }


    public StringBuffer append(StringBuffer stringBuffer, String string) {
        return stringBuffer.append(" ").append(string);
    }

    public StringBuffer append(StringBuffer stringBuffer, String $1, String $2, String $3) {
        return stringBuffer.append(" ").append($1).append(" ").append($2).append(".").append($3);
    }
}
